#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <limits.h>

// 曲目结构体：存储ID和名称
typedef struct {
    char *id;
    char *name;
} Track;

// 动态数组：存储所有有效曲目
typedef struct {
    Track *items;
    size_t count;
    size_t capacity;
} TrackList;

// 初始化曲目列表
void tracklist_init(TrackList *list) {
    list->items = NULL;
    list->count = 0;
    list->capacity = 0;
}

// 向列表添加曲目（自动扩容）
void tracklist_add(TrackList *list, const char *id, const char *name) {
    if (list->count >= list->capacity) {
        size_t new_cap = list->capacity == 0 ? 16 : list->capacity * 2;
        Track *new_items = realloc(list->items, new_cap * sizeof(Track));
        if (!new_items) {
            perror("内存分配失败");
            exit(EXIT_FAILURE);
        }
        list->items = new_items;
        list->capacity = new_cap;
    }
    // 复制ID和名称（避免指向临时缓冲区）
    list->items[list->count].id = strdup(id);
    list->items[list->count].name = strdup(name);
    list->count++;
}

// 释放曲目列表内存
void tracklist_free(TrackList *list) {
    for (size_t i = 0; i < list->count; i++) {
        free(list->items[i].id);
        free(list->items[i].name);
    }
    free(list->items);
    list->items = NULL;
    list->count = 0;
    list->capacity = 0;
}

// 去除字符串首尾空格和换行符（包括Windows的\r）
void trim_string(char *str) {
    if (!str || *str == '\0') return;

    // 去除尾部空格、\n、\r
    size_t len = strlen(str);
    while (len > 0) {
        char c = str[len - 1];
        if (c == ' ' || c == '\t' || c == '\n' || c == '\r') {
            len--;
        } else {
            break;
        }
    }
    str[len] = '\0';

    // 去除头部空格、\t
    size_t start = 0;
    while (str[start] == ' ' || str[start] == '\t') {
        start++;
    }

    // 移动字符串（如果头部有需要去除的字符）
    if (start > 0) {
        memmove(str, str + start, len - start + 1);
    }
}

// 解析chillhop.txt，提取有效曲目
void parse_chillhop_file(const char *filename, TrackList *tracks) {
    FILE *file = fopen(filename, "r");
    if (!file) {
        fprintf(stderr, "错误：无法打开文件 %s: %s\n", filename, strerror(errno));
        exit(EXIT_FAILURE);
    }

    char line[1024];
    while (fgets(line, sizeof(line), file)) {
        // 查找分隔符'!'
        char *sep = strchr(line, '!');
        if (!sep) continue; // 没有分隔符，跳过

        // 分割ID和名称
        *sep = '\0'; // 用'\0'截断，分离ID和名称
        char *id_part = line;
        char *name_part = sep + 1;

        // 修剪空格和换行符
        trim_string(id_part);
        trim_string(name_part);

        // 检查ID和名称是否非空
        if (strlen(id_part) == 0 || strlen(name_part) == 0) {
            continue;
        }

        // 添加到曲目列表
        tracklist_add(tracks, id_part, name_part);
    }

    fclose(file);

    if (tracks->count == 0) {
        fprintf(stderr, "错误：%s 中无有效曲目（格式应为 'ID!名称'）\n", filename);
        exit(EXIT_FAILURE);
    }
}

// 调用dmenu显示曲目列表，返回用户选择的曲目索引（-1表示取消）
int show_dmenu(TrackList *tracks) {
    int pipe_in[2], pipe_out[2];
    if (pipe(pipe_in) == -1 || pipe(pipe_out) == -1) {
        perror("管道创建失败");
        exit(EXIT_FAILURE);
    }

    pid_t pid = fork();
    if (pid == -1) {
        perror("fork失败");
        exit(EXIT_FAILURE);
    }

    if (pid == 0) { // 子进程：运行dmenu
        // 重定向输入（从pipe_in读）
        close(pipe_in[1]);
        dup2(pipe_in[0], STDIN_FILENO);
        close(pipe_in[0]);

        // 重定向输出（向pipe_out写）
        close(pipe_out[0]);
        dup2(pipe_out[1], STDOUT_FILENO);
        close(pipe_out[1]);

        // 执行dmenu（参数保持与原脚本一致）
        execlp("dmenu", "dmenu", "-i", "-c", (char*)NULL);
        perror("dmenu执行失败");
        exit(EXIT_FAILURE);
    }

    // 父进程：向dmenu发送曲目名称，读取选择结果
    close(pipe_in[0]);  // 关闭读端
    close(pipe_out[1]); // 关闭写端

    // 向dmenu写入所有曲目名称（每行一个）
    for (size_t i = 0; i < tracks->count; i++) {
        dprintf(pipe_in[1], "%s\n", tracks->items[i].name);
    }
    close(pipe_in[1]); // 写完关闭，让dmenu知道输入结束

    // 读取dmenu返回的选择结果
    char selected[1024] = {0};
    ssize_t n = read(pipe_out[0], selected, sizeof(selected) - 1);
    close(pipe_out[0]);

    // 等待子进程结束
    int status;
    waitpid(pid, &status, 0);
    if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
        return -1; // 用户取消选择或dmenu出错
    }

    // 去除选择结果中的换行符
    trim_string(selected);

    // 查找选择的曲目在列表中的索引
    for (size_t i = 0; i < tracks->count; i++) {
        if (strcmp(selected, tracks->items[i].name) == 0) {
            return i;
        }
    }

    return -1; // 未找到匹配（理论上不会发生）
}

// 创建缓存目录（递归创建，类似mkdir -p）
void create_cache_dir(const char *dir) {
    char tmp[PATH_MAX];
    size_t len = strlen(dir);
    if (len >= PATH_MAX) {
        fprintf(stderr, "错误：缓存目录路径过长\n");
        exit(EXIT_FAILURE);
    }
    strcpy(tmp, dir);

    // 逐个创建目录层级
    for (char *p = tmp + 1; *p; p++) {
        if (*p == '/') {
            *p = '\0';
            if (mkdir(tmp, 0755) == -1 && errno != EEXIST) {
                fprintf(stderr, "错误：创建目录 %s 失败: %s\n", tmp, strerror(errno));
                exit(EXIT_FAILURE);
            }
            *p = '/';
        }
    }

    // 创建最后一级目录
    if (mkdir(tmp, 0755) == -1 && errno != EEXIST) {
        fprintf(stderr, "错误：创建目录 %s 失败: %s\n", tmp, strerror(errno));
        exit(EXIT_FAILURE);
    }
}

// 发送通知（调用notify-send）
void send_notification(const char *message) {
    char cmd[1024];
    snprintf(cmd, sizeof(cmd), "notify-send 'Chillhop' '%s'", message);
    system(cmd); // 简单调用系统命令，性能影响可忽略
}

int main() {
    // 配置参数（与原脚本保持一致）
    const char *chillhop_file = "chillhop.txt";
    const char *cache_dir = NULL;
    const char *stream_base_url = "https://stream.chillhop.com/mp3/";
    const char *ffplay_path = "ffplay";

    // 获取缓存目录路径（$HOME/.cache/chillhop-player）
    char cache_dir_buf[PATH_MAX];
    const char *home = getenv("HOME");
    if (!home) {
        fprintf(stderr, "错误：未设置HOME环境变量\n");
        exit(EXIT_FAILURE);
    }
    snprintf(cache_dir_buf, sizeof(cache_dir_buf), "%s/.cache/chillhop-player", home);
    cache_dir = cache_dir_buf;

    // 解析曲目文件
    TrackList tracks;
    tracklist_init(&tracks);
    parse_chillhop_file(chillhop_file, &tracks);

    // 显示dmenu并获取用户选择
    int selected_idx = show_dmenu(&tracks);
    if (selected_idx == -1) {
        printf("用户取消选择\n");
        tracklist_free(&tracks);
        return 0;
    }
    Track *selected = &tracks.items[selected_idx];

    // 准备缓存文件路径
    char cache_file[PATH_MAX];
    snprintf(cache_file, sizeof(cache_file), "%s/%s.mp3", cache_dir, selected->id);

    // 创建缓存目录
    create_cache_dir(cache_dir);

    // 检查缓存文件是否存在，不存在则下载
    struct stat st;
    if (stat(cache_file, &st) != 0) { // 缓存不存在
        send_notification("正在下载...");
        printf("下载中：%s\n", selected->name);

        // 构建curl下载命令
        char curl_cmd[1024];
        snprintf(curl_cmd, sizeof(curl_cmd),
                 "curl -sSL '%s%s' -o '%s'",
                 stream_base_url, selected->id, cache_file);

        // 执行下载
        int ret = system(curl_cmd);
        if (ret != 0) {
            send_notification("下载失败");
            fprintf(stderr, "错误：下载失败\n");
            remove(cache_file); // 清理可能的不完整文件
            tracklist_free(&tracks);
            return 1;
        }
        send_notification("下载完成");
    } else {
        printf("使用缓存：%s\n", cache_file);
    }

    // 播放曲目（调用ffplay）
    send_notification("开始播放...");
    printf("正在播放：%s（按 q 退出）\n", selected->name);
    
    char ffplay_cmd[1024];
    snprintf(ffplay_cmd, sizeof(ffplay_cmd),
             "%s -nodisp -autoexit '%s'",
             ffplay_path, cache_file);
    system(ffplay_cmd);

    send_notification("播放结束");

    // 清理资源
    tracklist_free(&tracks);
    return 0;
}
